package com.mingqijia.gassafety.authority.security.user;

import com.gap.cache.redis.RedisCache;
import com.mingqijia.gassafety.authority.dal.command.UpdateManagerCommand;
import com.mingqijia.gassafety.authority.dal.provider.CompanyProvider;
import com.mingqijia.gassafety.authority.dal.provider.ManagerProvider;
import com.mingqijia.gassafety.authority.dal.provider.RoleProvider;
import com.mingqijia.gassafety.authority.security.valueobject.ManagerVO;
import com.mingqijia.gassafety.db.entity.auth.CompanyEntry;
import com.mingqijia.gassafety.db.entity.auth.ManagerEntry;
import com.mingqijia.gassafety.db.entity.auth.RoleEntry;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import com.mingqijia.gassafety.shared.user.UserBackend;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.MappingTools;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户信息统一处理类
 * @author Damon S.
 * @version v0.2
 * @date 2022-02-28 18:47
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class SecurityUserLoginHolder {

    private final RedisCache cacheManager;
    private final RoleProvider rProvider;
    private final SecurityUserTranslator translator;
    private final ManagerProvider provider;
    private final CompanyProvider cProvider;


    public ManagerVO findManagerByUsername(String username) {
        ManagerVO backend;
        String cachedUserBackend = cacheManager.getCacheObject(
                String.format(Constants.KEY_MANAGE_PROFILE, username));
        if (ObjectUtils.isEmpty(cachedUserBackend)) {
            // 从数据库中取数据
            backend = translator.toVO(provider.getByUsername(username));
        } else {
            // 从缓存中取数据
            backend = ApplicationUtils.toBean(cachedUserBackend, ManagerVO.class);
        }
        if (ObjectUtils.isEmpty(backend)) {
            throw new GlobalAuthenticationException("用户不存在"+username);
        }
        backend.setPassword(null);
        cacheWorkingUserState(backend);
        return backend;
    }

    public void whenWorkingSpIdChanged(String spId) {
        CompanyEntry entry = cProvider.getById(spId);
        if (ObjectUtils.isEmpty(entry)) {
            throw new GlobalAuthenticationException("spId不存在");
        }
        // 更新最近使用企业
        UserBackend backend = ApplicationUtils.getWorkingUser();
        UpdateManagerCommand command = UpdateManagerCommand.builder()
                .workingSpId(spId).userId(backend.getUserId()).build();
        if (!provider.update(command)) {
            log.error("更新用户信息[user={}, workingSpId={}]失败", backend.getUsername(), spId);
            throw new GlobalAuthenticationException("系统错误，更新用户信息失败");
        }
        ((ManagerVO) backend).setWorkingSpId(spId);
        // 缓存用户信息
        cacheWorkingUserState(backend);
    }

    public void whenManagerUpdated(String userId) {
        ManagerEntry entry = provider.getById(userId);
        cacheManager.deleteObject(String.format(Constants.KEY_MANAGE_PROFILE, entry.getUsername()));
    }

    public void whenManagerLogin(ManagerVO backend) {
        UpdateManagerCommand command = UpdateManagerCommand.builder()
                .logoutAt(MappingTools.DEFAULT_MAX_LDT).updatedBy(backend.getUserId())
                .loginAt(MappingTools.getCurrent()).userId(backend.getUserId()).build();
        if (!provider.update(command)) {
            throw new GlobalAuthenticationException("更新用户登录信息失败");
        }
        // 先清一下密码
        backend.setPassword(null);
        backend.setLogoutAt(command.getLogoutAt());
        backend.setLoginAt(command.getLoginAt());

        // 设置角色
        List<RoleEntry> entries = rProvider.findValidRoles(backend.getRoleIds());
        backend.setRoleIds(entries.stream().map(RoleEntry::getId).collect(Collectors.toList()));
        // 缓存用户信息
        cacheWorkingUserState(backend);
    }

    public void whenManagerLogout(ManagerVO backend) {
        // 设置登出时间，再更新数据库用户登出
        UpdateManagerCommand command = UpdateManagerCommand.builder()
                .userId(backend.getUserId()).updatedBy(backend.getUserId())
                .logoutAt(MappingTools.getCurrent()).build();
        provider.update(command);
        // 更新缓存
        backend.setLogoutAt(command.getLogoutAt());
        cacheWorkingUserState(backend);
    }

    public ManagerVO findManagerFromDb(String username) {
        ManagerEntry backend = provider.getByUsername(username);
        if (ObjectUtils.isEmpty(backend)) {
            throw new GlobalAuthenticationException("用户名或密码错误");
        }
        return translator.toVO(backend);
    }

    private void cacheWorkingUserState(UserBackend backend) {
        cacheManager.setCacheObject(String.format(Constants.KEY_MANAGE_PROFILE, backend.getUsername()),
                ApplicationUtils.toJson(backend), Constants.INT_TWO, TimeUnit.HOURS);
    }
}
